#pragma once

#include "noncopyable.h"
#include "EventLoop.h"
#include "Acceptor.h"
#include "InetAddress.h"
#include "EventLoopThreadPool.h"
#include "Callback.h"

#include <functional>
#include <string>
#include <atomic>
#include <unordered_map>

class TcpServer : noncopyable {
public:
  using ThreadInitCallback = std::function<void(EventLoop*)>;
  enum Option {
    kNoReusePort = 1, // SO_REUSEPORT
    kReusePort = 2,
  };
  TcpServer(EventLoop* loop, const InetAddress& listenAddr, const std::string& nameArg,
           Option option = kNoReusePort);
  ~TcpServer();
  void setThreadNum(int numThreads);
  void setConnectionCallback(const ConnectionCallback& cb) {
    m_connectionCallback = cb;
  }
  void setWriteCompleteCallback(const WriteCompleteCallback& cb) {
    m_writeCompleteCallback = cb;
  }
  void setMessageCallback(const MessageCallback& cb) {
    m_messageCallback = cb;
  }
  void setThreadInitCallback(const ThreadInitCallback& cb) {
    m_threadInitCallback = cb;
  }
  void start();
private:
  void newConnection(int sockfd, const InetAddress& peerAddr);
  void removeConnection(const TcpConnectionPtr& conn);
  void removeConnectionInLoop(const TcpConnectionPtr& conn);
private:
  EventLoop *m_loop;
  const std::string m_ipPort;
  const std::string m_name;
  std::unique_ptr<Acceptor> m_acceptor; // 运行在 mainLoop，主要是监听新事件
  std::shared_ptr<EventLoopThreadPool> m_pool;
  ConnectionCallback m_connectionCallback; // 有新连接时的回调
  WriteCompleteCallback m_writeCompleteCallback; // 消息发送完成以后的回调
  MessageCallback m_messageCallback; // 接收到消息时的回调
  ThreadInitCallback m_threadInitCallback; // 线程初始化回调
  std::atomic<int> m_started;
  int m_nextConnId;
  std::unordered_map<std::string, TcpConnectionPtr> m_connections;
};